package com.goresor.util;

import java.awt.Desktop;
import java.awt.Desktop.Action;
import java.io.IOException;
import java.net.URI;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.google.api.client.auth.oauth.OAuthAuthorizeTemporaryTokenUrl;
import com.google.api.client.auth.oauth.OAuthCredentialsResponse;
import com.google.api.client.auth.oauth.OAuthHmacSigner;
import com.google.api.client.auth.oauth.OAuthParameters;
import com.google.api.client.googleapis.auth.oauth.GoogleOAuthGetAccessToken;
import com.google.api.client.googleapis.auth.oauth.GoogleOAuthGetTemporaryToken;
import com.google.common.base.Preconditions;

@Component
public class GoogleTokenManager {

	public static final Logger log = LoggerFactory
			.getLogger(GoogleTokenManager.class);

	/**
	 * Domain identifying the third-party web application. This is the domain
	 * used when registering the application with Google.
	 */
	@Value("${goresor.consumer.key}")
	private String oauth_consumer_key_value;

	/**
	 * Random 64-bit, unsigned number encoded as an ASCII string in decimal
	 * format. The nonce/timestamp pair should always be unique to prevent
	 * replay attacks.
	 */
	/**
	 * Signature algorithm. The legal values for this parameter "RSA-SHA1" or
	 * "HMAC-SHA1". Google does not support "PLAINTEXT".
	 */
	// private static final String oauth_signature_method =
	// "oauth_signature_method";

	// @Value("${goresor.oauth_signature_method}")
	// private String oauth_signature_method_value;

	/**
	 * String generated using the referenced signature method. See Signing
	 * requests.
	 */
	// private static final String oauth_signature = "oauth_signature";

	@Value("${goresor.consumer.secret}")
	private String oauth_signature_value;

	/**
	 * Integer representing the time the request is sent. The timestamp should
	 * be expressed in number of seconds after January 1, 1970 00:00:00 GMT.
	 */
	// private static final String oauth_timestamp = "oauth_timestamp";
	/**
	 * URL identifying the service(s) to be accessed. The resulting token
	 * enables access to the specified service(s) only. Scopes are defined by
	 * each Google service; see the service's documentation for the correct
	 * value. To specify more than one scope, list each one separated with a
	 * space. This parameter is not defined in the OAuth standards; it is a
	 * Google-specific parameter.
	 */
	// private static final String scope = "scope";

	// @Value("${goresor.scope}")
	// private String scope_value;
	/**
	 * (required) URL the user should be redirected to after access to a Google
	 * service(s) is granted (in response to a call to OAuthAuthorizeToken). The
	 * response to this OAuthGetRequestToken call verifies that Google handles a
	 * callback URL. The callback URL can include url-encoded query parameters.
	 * To trigger an alternative sequence, in which Google displays a success
	 * page with a verification code that the user must then supply to the
	 * third-party application, use the value "oob". In the subsequent call to
	 * OAuthGetAccessToken, the parameter verifier must be set to this value.
	 */
	// private static final String oauth_callback = "oauth_callback";

	@Value("${goresor.oauthcallback}")
	private String oauth_callback_value;

	// private String xoauth_displayname = "xoauth_displayname";

	/**
	 * nom de l'appli affiché lors de l'acceptation par le user.
	 */
	// @Value("${goresor.xoauth_displayname_value}")
	// private String xoauth_displayname_value;

	// private DefaultHttpClient httpclient = new DefaultHttpClient();

	private String tempToken = null;
	private OAuthHmacSigner signer;

	@Value("${goresor.nom.application}")
	private static String APP_NAME;

	/**
	 * Exchange the authorized request token for an access token
	 * 
	 * @param oauth_verifier
	 * @throws IOException
	 */
	public void authorizeAccess(String oauth_verifier) throws IOException {
		GoogleOAuthGetAccessToken accessToken = this
				.getAccessToken(oauth_verifier);
		OAuthCredentialsResponse credentials = accessToken.execute();
		signer.tokenSharedSecret = credentials.tokenSecret;

		OAuthParameters authorizer = new OAuthParameters();
		authorizer.consumerKey = oauth_consumer_key_value;
		authorizer.signer = signer;
		authorizer.token = credentials.token;
		authorizer.version = "1.0";
		authorizer
				.signRequestsUsingAuthorizationHeader(GoogleTransportUtil.TRANSPORT);
		log.info("tokenSecret " + signer.tokenSharedSecret);
	}

	private GoogleOAuthGetAccessToken getAccessToken(String oauth_verifier) {
		GoogleOAuthGetAccessToken accessToken = new GoogleOAuthGetAccessToken();
		accessToken.transport = GoogleTransportUtil.AUTH_TRANSPORT;
		accessToken.temporaryToken = tempToken;
		accessToken.signer = signer;
		accessToken.consumerKey = oauth_consumer_key_value;
		accessToken.verifier = oauth_verifier;
		return accessToken;
	}

	public String requestOAuthToken() throws Exception {

		// temporary token
		OAuthCredentialsResponse tempCredentials = this.requestTemporaryToken();
		// demande d'autorisation de l'utilisateur
		log.info("retour suite a autorisation");
		return this.requestAutorisation(tempCredentials);

	}

	/**
	 * Authorize the request token
	 * 
	 * @param tempCredentials
	 * @throws IOException
	 */
	private String requestAutorisation(OAuthCredentialsResponse tempCredentials)
			throws IOException {
		OAuthAuthorizeTemporaryTokenUrl authorizeUrl = new OAuthAuthorizeTemporaryTokenUrl(
				"https://www.google.com/latitude/apps/OAuthAuthorizeToken");
		// (required) The domain used to identify your application.
		authorizeUrl.put("domain", oauth_consumer_key_value);
		// (optional) The range of locations you want to access. Can be either
		// current or all. If this parameter is omitted, current is assumed.
		authorizeUrl.put("location", "all");
		// (optional) The finest granularity of locations you want to access.
		// Can
		// be either city or best. If this parameter is omitted, city is
		// assumed.
		authorizeUrl.put("granularity", "best");

		authorizeUrl.temporaryToken = tempToken = tempCredentials.token;
		String authorizationUrl = authorizeUrl.build();
		log.info("authorizationUrl " + authorizationUrl);
		// // launch in browser
		// boolean browsed = false;
		// if (Desktop.isDesktopSupported()) {
		// Desktop desktop = Desktop.getDesktop();
		// if (desktop.isSupported(Action.BROWSE)) {
		// desktop.browse(URI.create(authorizationUrl));
		// browsed = true;
		// }
		// }
		// if (!browsed) {
		// String browser = "google-chrome";
		// Runtime.getRuntime().exec(new String[] { browser, authorizationUrl
		// });
		// }
		return authorizationUrl;
	}

	/**
	 * Get an unauthorized request token
	 * 
	 * @return
	 * @throws IOException
	 */
	private OAuthCredentialsResponse requestTemporaryToken() throws IOException {
		GoogleOAuthGetTemporaryToken temporaryToken = new GoogleOAuthGetTemporaryToken();
		signer = new OAuthHmacSigner();
		signer.clientSharedSecret = Preconditions
				.checkNotNull(oauth_signature_value);
		temporaryToken.transport = GoogleTransportUtil.AUTH_TRANSPORT;
		temporaryToken.signer = signer;
		temporaryToken.consumerKey = Preconditions
				.checkNotNull(oauth_consumer_key_value);
		temporaryToken.scope = "https://www.googleapis.com/auth/latitude";
		temporaryToken.displayName = APP_NAME;
		temporaryToken.callback = oauth_callback_value;
		log.info("temporaryToken :" + temporaryToken);
		OAuthCredentialsResponse tempCredentials = temporaryToken.execute();
		signer.tokenSharedSecret = tempCredentials.tokenSecret;
		log.info("tempCredentials.tokenSecret :" + tempCredentials.tokenSecret);
		return tempCredentials;
	}

	// private void requestOAuthToken() throws Exception {
	//
	// // temporary token
	// GoogleOAuthGetTemporaryToken temporaryToken = new
	// GoogleOAuthGetTemporaryToken();
	// signer = new OAuthHmacSigner();
	// signer.clientSharedSecret = Preconditions
	// .checkNotNull(oauth_signature_value);
	// temporaryToken.transport = Util.AUTH_TRANSPORT;
	// temporaryToken.signer = signer;
	// temporaryToken.consumerKey = Preconditions
	// .checkNotNull(oauth_consumer_key_value);
	// temporaryToken.scope = "https://www.googleapis.com/auth/latitude";
	// temporaryToken.displayName = APP_NAME;
	// temporaryToken.callback = oauth_callback_value;
	// log.info("temporaryToken :" + temporaryToken);
	// OAuthCredentialsResponse tempCredentials = temporaryToken.execute();
	// signer.tokenSharedSecret = tempCredentials.tokenSecret;
	// log.info("tempCredentials.tokenSecret :" + tempCredentials.tokenSecret);
	//
	// OAuthAuthorizeTemporaryTokenUrl authorizeUrl = new
	// OAuthAuthorizeTemporaryTokenUrl(
	// "https://www.google.com/latitude/apps/OAuthAuthorizeToken");
	// // (required) The domain used to identify your application.
	// authorizeUrl.put("domain", oauth_consumer_key_value);
	// // (optional) The range of locations you want to access. Can be either
	// // current or all. If this parameter is omitted, current is assumed.
	// authorizeUrl.put("location", "all");
	// // (optional) The finest granularity of locations you want to access.
	// // Can
	// // be either city or best. If this parameter is omitted, city is
	// // assumed.
	// authorizeUrl.put("granularity", "best");
	//
	// authorizeUrl.temporaryToken = tempToken = tempCredentials.token;
	// String authorizationUrl = authorizeUrl.build();
	// log.info("authorizationUrl " + authorizationUrl);
	// // launch in browser
	// boolean browsed = false;
	// if (Desktop.isDesktopSupported()) {
	// Desktop desktop = Desktop.getDesktop();
	// if (desktop.isSupported(Action.BROWSE)) {
	// desktop.browse(URI.create(authorizationUrl));
	// browsed = true;
	// }
	// }
	// if (!browsed) {
	// String browser = "google-chrome";
	// Runtime.getRuntime().exec(
	// new String[] { browser, authorizationUrl });
	// }
	// log.info("retour suite a autorisation");
	//
	// }

	// private OAuthParameters getAuthorizer(OAuthCredentialsResponse
	// credentials) {
	// OAuthParameters authorizer = new OAuthParameters();
	// authorizer.consumerKey = oauth_consumer_key_value;
	// authorizer.signer = signer;
	// authorizer.token = credentials.token;
	// return authorizer;
	// }

	// private GoogleOAuthGetAccessToken getAccessToken(String oauth_verifier) {
	// GoogleOAuthGetAccessToken accessToken = new GoogleOAuthGetAccessToken();
	// accessToken.transport = Util.AUTH_TRANSPORT;
	// accessToken.temporaryToken = tempToken;
	// accessToken.signer = signer;
	// accessToken.consumerKey = oauth_consumer_key_value;
	// accessToken.verifier = oauth_verifier;
	// return accessToken;
	// }

	// private void authorizeAccess(String oauth_verifier) throws IOException {
	// GoogleOAuthGetAccessToken accessToken = this
	// .getAccessToken(oauth_verifier);
	// OAuthCredentialsResponse credentials = accessToken.execute();
	// signer.tokenSharedSecret = credentials.tokenSecret;
	//
	// OAuthParameters authorizer = this.getAuthorizer(credentials);
	// authorizer.signRequestsUsingAuthorizationHeader(Util.TRANSPORT);
	// log.info("tokenSecret " + signer.tokenSharedSecret);
	// }

}
